﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using TCC.CMFlow.Models;
using TCC.CMFlow.Contexts;
using Microsoft.AspNet.Identity;
using TCC.CMFlow.Models.Enumerators;
using TCC.CMFlow.Business;
using Microsoft.Reporting.WebForms;
using System.IO;

namespace TCC.CMFlow.Controllers
{
    [Authorize]
    public class WorkflowController : Controller
    {
        private DataContext db = new DataContext();

        // GET: /Workflow/
        [AuthorizeUserAttribute(Modulo = eModulosSistema.Aprovacoes)]
        public ActionResult Index()
        {
            WorkflowBusiness wb = new WorkflowBusiness();
            wb.ProcessarWorkflowsETL();

            var grupos = db.CategoriaWorkflow.Where(CategoriaWorkflow.IsAtivoExpression).ToList();
            ViewBag.WorkflowCategoria = new SelectList(grupos, "ID", "Nome");

            Dictionary<int, string> statusWorkflow = new Dictionary<int, string>();
            var statusIds = Enum.GetValues(typeof(EnumStatusWorkflow)).Cast<int>().ToList();
            statusIds.ForEach(s => statusWorkflow.Add(s, Enum.GetName(typeof(EnumStatusWorkflow), s)));
            ViewBag.WorkflowStatus = new SelectList(statusWorkflow, "Key", "Value");

            var workflows = db.Workflow.Include(w => w.CategoriaWorkflow);
            return View(workflows.ToList());
        }

        [AuthorizeUserAttribute(Modulo = eModulosSistema.Aprovacoes, Permissao = ePermissoes.Consultar)]
        public ActionResult Search(string ID, string WorkflowCategoria, string emissaoDe, string emissaoAte, string WorkflowStatus)
        {
            long _ID;
            long.TryParse(ID, out _ID);

            long _IDCategoria;
            long.TryParse(WorkflowCategoria, out _IDCategoria);

            long _status;
            long.TryParse(WorkflowStatus, out _status);

            DateTime _emissaoDe;
            DateTime.TryParse(emissaoDe, out _emissaoDe);

            DateTime _emissaoAte;
            DateTime.TryParse(emissaoAte, out _emissaoAte);

            var grupos = db.CategoriaWorkflow.Where(CategoriaWorkflow.IsAtivoExpression).ToList();
            ViewBag.WorkflowCategoria = new SelectList(grupos, "ID", "Nome", WorkflowCategoria);

            Dictionary<int, string> statusWorkflow = new Dictionary<int, string>();
            var statusIds = Enum.GetValues(typeof(EnumStatusWorkflow)).Cast<int>().ToList();
            statusIds.ForEach(s => statusWorkflow.Add(s, Enum.GetName(typeof(EnumStatusWorkflow), s)));
            ViewBag.WorkflowStatus = new SelectList(statusWorkflow, "Key", "Value", WorkflowStatus);

            var workflows = from w in db.Workflow
                            select w;

            if (_ID > 0)
            {
                workflows = workflows.Where(g => g.ID == _ID);
            }

            if (_IDCategoria > 0)
            {
                workflows = workflows.Where(w => w.CategoriaWorkflow.ID == _IDCategoria);
            }

            if (_emissaoDe != null && _emissaoDe != DateTime.MinValue)
            {
                workflows = workflows.Where(w => w.DataEmissao >= _emissaoDe);
            }

            if (_emissaoAte != null && _emissaoAte != DateTime.MinValue)
            {
                _emissaoAte = _emissaoAte.AddHours(23).AddMinutes(59).AddSeconds(59);

                workflows = workflows.Where(w => w.DataEmissao <= _emissaoAte);
            }

            if (!string.IsNullOrEmpty(WorkflowStatus))
            {
                workflows = workflows.Where(w => w.Status == _status);
            }

            return View("Index", workflows.ToList());
        }

        // GET: /Workflow/Details/5
        [AuthorizeUserAttribute(Modulo = eModulosSistema.Aprovacoes, Permissao = ePermissoes.Visualizar)]
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            Workflow workflow = db.Workflow.Find(id);
            if (workflow == null)
            {
                return HttpNotFound();
            }

            ViewBag.ExibeControles = this.ExibeControlesAprovacao(workflow);
            ViewBag.PermiteReprocessamento = this.PermiteReprocessamento(workflow);

            return View(workflow);
        }

        // GET: /Workflow/Create
        [AuthorizeUserAttribute(Modulo = eModulosSistema.Aprovacoes, Permissao = ePermissoes.Incluir, isModal = true)]
        public ActionResult Create()
        {
            ViewBag.CategoriaWorkflowID = new SelectList(db.CategoriaWorkflow, "ID", "Nome");
            return View();
        }

        // POST: /Workflow/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include="ID,CategoriaWorkflowID,Status,DataEmissao")] Workflow workflow)
        {
            if (ModelState.IsValid)
            {
                db.Workflow.Add(workflow);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            ViewBag.CategoriaWorkflowID = new SelectList(db.CategoriaWorkflow, "ID", "Nome", workflow.CategoriaWorkflowID);
            return View(workflow);
        }

        // GET: /Workflow/Edit/5
        [AuthorizeUserAttribute(Modulo = eModulosSistema.Aprovacoes, Permissao = ePermissoes.Editar, isModal = true)]
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Workflow workflow = db.Workflow.Find(id);
            if (workflow == null)
            {
                return HttpNotFound();
            }
            ViewBag.CategoriaWorkflowID = new SelectList(db.CategoriaWorkflow, "ID", "Nome", workflow.CategoriaWorkflowID);
            return View(workflow);
        }

        // POST: /Workflow/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include="ID,CategoriaWorkflowID,Status,DataEmissao")] Workflow workflow)
        {
            if (ModelState.IsValid)
            {
                db.Entry(workflow).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            ViewBag.CategoriaWorkflowID = new SelectList(db.CategoriaWorkflow, "ID", "Nome", workflow.CategoriaWorkflowID);
            return View(workflow);
        }

        // GET: /Workflow/AprovarWorkflow/5
        [AuthorizeUserAttribute(Modulo = eModulosSistema.Aprovacoes, Permissao = ePermissoes.Editar, isModal = true)]
        public ActionResult AprovarWorkflow(int? workflowID)
        {
            if (workflowID == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Workflow workflow = db.Workflow.Find(workflowID);
            if (workflow == null)
            {
                return HttpNotFound();
            }

            return PartialView(new WorkflowAprovacao());
        }

        // POST: /Workflow/AprovarWorkflow/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult AprovarWorkflow(int workflowID, string observacao)
        {
            try
            {
                Workflow workflow = db.Workflow.Find(workflowID);
                if (workflow == null)
                {
                    return HttpNotFound();
                }

                if (ModelState.IsValid)
                {
                    //// Gera um registro de aprovação
                    var workflowAprovacao = new WorkflowAprovacao()
                    {
                        WorkflowID = workflowID,
                        DataHoraAprovacao = DateTime.Now,
                        UsuarioID = this.User.Identity.GetUserId(),
                        Status = (int)EnumStatusWorkflow.Aprovado,
                        Observacao = observacao
                    };

                    db.WorkflowAprovacao.Add(workflowAprovacao);
                    db.SaveChanges();

                    //// Atualiza o status do Workflow
                    if (this.AprovaConsolidado(workflow))
                    {
                        workflow.Status = (int)EnumStatusWorkflow.Aprovado;
                    }
                    else
                    {
                        workflow.Status = (int)EnumStatusWorkflow.Pendente;
                    }

                    db.Entry(workflow).State = EntityState.Modified;
                    db.SaveChanges();

                    return Json(new { success = true });
                }

                return PartialView(new WorkflowAprovacao());
            }
            catch (Exception ex)
            {
                Logger.AddLog(EnumTipoLog.Erro, (int)eModulosSistema.Aprovacoes, this.User.Identity.GetUserId(), ex.Message);

                throw ex;
            }
        }

        // GET: /Workflow/AprovarWorkflow/5
        [AuthorizeUserAttribute(Modulo = eModulosSistema.Aprovacoes, Permissao = ePermissoes.Editar, isModal = true)]
        public ActionResult ReprovarWorkflow(int? workflowID)
        {
            if (workflowID == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Workflow workflow = db.Workflow.Find(workflowID);
            if (workflow == null)
            {
                return HttpNotFound();
            }

            ViewBag.WorkflowDados = new MultiSelectList(workflow.Dados, "ID", "NomeAtributo");

            return PartialView(new WorkflowAprovacao());
        }

        // POST: /Workflow/AprovarWorkflow/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult ReprovarWorkflow(int workflowID, long[] WorkflowDadosList, string observacao)
        {
            try
            {
                Workflow workflow = db.Workflow.Find(workflowID);
                if (workflow == null)
                {
                    return HttpNotFound();
                }

                if (WorkflowDadosList == null)
                {
                    ModelState.AddModelError("Atributos", "Nenhum Atributo foi selecionado.");
                    ViewBag.WorkflowDados = new MultiSelectList(workflow.Dados, "ID", "NomeAtributo");

                    return PartialView(new WorkflowAprovacao());
                }

                if (ModelState.IsValid)
                {
                    //// Gera um registro de reprovação
                    var workflowAprovacao = new WorkflowAprovacao()
                    {
                        WorkflowID = workflowID,
                        DataHoraAprovacao = DateTime.Now,
                        UsuarioID = this.User.Identity.GetUserId(),
                        Status = (int)EnumStatusWorkflow.Reprovado,
                        Observacao = observacao
                    };

                    var dados = workflow.Dados.Where(d => WorkflowDadosList.Contains(d.ID)).ToList();
                    if (dados.Any())
                    {
                        workflowAprovacao.Dados = new List<WorkflowAprovacaoDado>();
                        dados.ForEach(d => workflowAprovacao.Dados.Add(new WorkflowAprovacaoDado() { NomeAtributo = d.NomeAtributo, ValorAtributo = d.ValorAtributo }));
                    }

                    db.WorkflowAprovacao.Add(workflowAprovacao);
                    db.SaveChanges();

                    //// Atualiza o status do Workflow
                    workflow.Status = (int)EnumStatusWorkflow.Reprovado;
                    db.Entry(workflow).State = EntityState.Modified;
                    db.SaveChanges();

                    return Json(new { success = true });
                }

                ViewBag.WorkflowDados = new MultiSelectList(workflow.Dados, "ID", "NomeAtributo");

                return PartialView(new WorkflowAprovacao());
            }
            catch (Exception ex)
            {
                Logger.AddLog(EnumTipoLog.Erro, (int)eModulosSistema.Aprovacoes, this.User.Identity.GetUserId(), ex.Message);

                throw ex;
            }
        }

        // GET: /Workflow/CancelarWorkflow/5
        [AuthorizeUserAttribute(Modulo = eModulosSistema.Aprovacoes, Permissao = ePermissoes.Editar, isModal = true)]
        public ActionResult CancelarWorkflow(int? workflowID)
        {
            if (workflowID == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            Workflow workflow = db.Workflow.Find(workflowID);
            if (workflow == null)
            {
                return HttpNotFound();
            }

            return PartialView(new WorkflowAprovacao());
        }

        // POST: /Workflow/CancelarWorkflow/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CancelarWorkflow(int workflowID, string observacao)
        {
            try
            {
                Workflow workflow = db.Workflow.Find(workflowID);
                if (workflow == null)
                {
                    return HttpNotFound();
                }

                if (ModelState.IsValid)
                {
                    //// Gera um registro de cancelamento
                    var workflowAprovacao = new WorkflowAprovacao()
                    {
                        WorkflowID = workflowID,
                        DataHoraAprovacao = DateTime.Now,
                        UsuarioID = User.Identity.GetUserId(),
                        Status = (int)EnumStatusWorkflow.Cancelado,
                        Observacao = observacao
                    };

                    db.WorkflowAprovacao.Add(workflowAprovacao);
                    db.SaveChanges();

                    //// Atualiza o status do Workflow
                    workflow.Status = (int)EnumStatusWorkflow.Cancelado;
                    db.Entry(workflow).State = EntityState.Modified;
                    db.SaveChanges();

                    return Json(new { success = true });
                }

                return PartialView(new WorkflowAprovacao());
            }
            catch (Exception ex)
            {
                Logger.AddLog(EnumTipoLog.Erro, (int)eModulosSistema.Aprovacoes, this.User.Identity.GetUserId(), ex.Message);

                throw ex;
            }
        }

        // GET: /Workflow/ReprocessarWorkflow/5
        [AuthorizeUserAttribute(Modulo = eModulosSistema.Aprovacoes, Permissao = ePermissoes.Editar, isModal = true)]
        public ActionResult ReprocessarWorkflow(int? workflowID)
        {
            if (workflowID == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            Workflow workflow = db.Workflow.Find(workflowID);
            if (workflow == null)
            {
                return HttpNotFound();
            }

            return PartialView(new WorkflowAprovacao());
        }

        // POST: /Workflow/ReprocessarWorkflow/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult ReprocessarWorkflow(int workflowID, string observacao)
        {
            try
            {
                Workflow workflow = db.Workflow.Find(workflowID);
                if (workflow == null)
                {
                    return HttpNotFound();
                }

                if (ModelState.IsValid)
                {
                    //// Gera um registro de reprocessamento
                    var workflowAprovacao = new WorkflowAprovacao()
                    {
                        WorkflowID = workflowID,
                        DataHoraAprovacao = DateTime.Now,
                        UsuarioID = User.Identity.GetUserId(),
                        Status = (int)EnumStatusWorkflow.Reprocessamento,
                        Observacao = observacao
                    };

                    db.WorkflowAprovacao.Add(workflowAprovacao);
                    db.SaveChanges();

                    //// Atualiza o status do Workflow
                    workflow.Status = (int)EnumStatusWorkflow.Reprocessamento;
                    db.Entry(workflow).State = EntityState.Modified;
                    db.SaveChanges();

                    return Json(new { success = true });
                }

                return PartialView(new WorkflowAprovacao());
            }
            catch (Exception ex)
            {
                Logger.AddLog(EnumTipoLog.Erro, (int)eModulosSistema.Aprovacoes, this.User.Identity.GetUserId(), ex.Message);
   
                throw ex;
            }
        }

        public ActionResult Report(int workflowID, string id)
        {
            LocalReport lr = new LocalReport();
            string path = Path.Combine(Server.MapPath("~/Reporting"), "Workflows.rdlc");

            if (System.IO.File.Exists(path))
            {
                lr.ReportPath = path;
            }
            else
            {
                throw new Exception("Caminho do relatório não encontrado!");
            }

            List<Workflow> workflow = db.Workflow.Where(w => w.ID == workflowID).ToList();
            if (workflow == null || !workflow.Any())
            {
                return HttpNotFound();
            }

            var workflowDS = (from w in workflow
                              select new
                              {
                                  ID = w.ID,
                                  CategoriaWorkflowID = w.CategoriaWorkflowID,
                                  Status = w.Status,
                                  DataEmissao = w.DataEmissao,
                                  NomeCategoria = w.CategoriaWorkflow.Nome,
                                  DescricaoCategoria = w.CategoriaWorkflow.Descricao,
                                  DescricaoStatus = w.DescricaoStatus
                             }).ToList();
            ReportDataSource rdsWorkflow = new ReportDataSource("WorkflowDS", workflowDS);
            lr.DataSources.Add(rdsWorkflow);

            ReportDataSource rdsDados = new ReportDataSource("WorkflowDadoDS", workflow.SelectMany(w => w.Dados).ToList());
            lr.DataSources.Add(rdsDados);

            var workflowAprovacaoDS = (from w in workflow.SelectMany(w => w.Aprovacoes)
                                       select new
                                       {
                                           ID = w.ID,
                                           WorkflowID = w.WorkflowID,
                                           UsuarioID = w.UsuarioID,
                                           DataHoraAprovacao = DateTime.Now,
                                           Observacao = w.Observacao,
                                           Status = w.Status,
                                           NomeUsuario = (w.Usuario != null ? w.Usuario.Nome : null),
                                           NomeGrupo = w.Usuario != null
                                                ? w.Workflow.CategoriaWorkflow.CategoriaGrupos
                                                    .Where(c => c.Usuarios.Contains(w.Usuario))
                                                    .Select(s => s.GrupoAprovacao != null ? s.GrupoAprovacao.Nome : null)
                                                    .FirstOrDefault()
                                                : null,
                                           DescricaoStatus = w.DescricaoStatus
                                       }).ToList();

            ReportDataSource rdsAprovacoes = new ReportDataSource("WorkflowAprovacaoDS", workflowAprovacaoDS);
            lr.DataSources.Add(rdsAprovacoes);

            string reportType = id;
            string mimeType;
            string encoding;
            string fileNameExtension;

            string deviceInfo =
                "<DeviceInfo>" +
                    "<OutputFormat>" + id + "</OutputFormat>" +
                "</DeviceInfo>";

            Warning[] warnings;
            string[] streams;
            byte[] renderedBytes;

            renderedBytes = lr.Render(
                reportType,
                deviceInfo,
                out mimeType,
                out encoding,
                out fileNameExtension,
                out streams,
                out warnings
            );

            return File(renderedBytes, mimeType);
        }

        public ActionResult Notificacoes()
        {
            var workflows = db.Workflow.ToList();

            List<Workflow> listaWorkflowsNotificacao = new List<Workflow>();
            foreach (var workflow in workflows)
            {
                if (this.ExibeControlesAprovacao(workflow))
                {
                    listaWorkflowsNotificacao.Add(workflow);
                }
            }

            return PartialView(listaWorkflowsNotificacao);
        }

        // GET: /Workflow/Delete/5
        [AuthorizeUserAttribute(Modulo = eModulosSistema.Aprovacoes, Permissao = ePermissoes.Excluir, isModal = true)]
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Workflow workflow = db.Workflow.Find(id);
            if (workflow == null)
            {
                return HttpNotFound();
            }
            return View(workflow);
        }

        // POST: /Workflow/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Workflow workflow = db.Workflow.Find(id);
            db.Workflow.Remove(workflow);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }

        // GET: /Workflow/StatusAprovacao/5
        public ActionResult StatusAprovacao(EnumStatusWorkflow status)
        {
            switch (status)
            {
                case EnumStatusWorkflow.Gerado:
                    return Content("<span class=\"text-primary glyphicon glyphicon-saved\"></span> " + EnumStatusWorkflow.Gerado.ToString());
                case EnumStatusWorkflow.Pendente:
                    return Content("<span class=\"text-info glyphicon glyphicon-dashboard\"></span> " + EnumStatusWorkflow.Pendente.ToString());
                case EnumStatusWorkflow.Aprovado:
                    return Content("<span class=\"text-success glyphicon glyphicon-thumbs-up\"></span> " + EnumStatusWorkflow.Aprovado.ToString());
                case EnumStatusWorkflow.Reprovado:
                    return Content("<span class=\"text-danger glyphicon glyphicon-thumbs-down\"></span> " + EnumStatusWorkflow.Reprovado.ToString());
                case EnumStatusWorkflow.Cancelado:
                    return Content("<span class=\"text-warning glyphicon glyphicon-remove\"></span> " + EnumStatusWorkflow.Cancelado.ToString());
                case EnumStatusWorkflow.Reprocessamento:
                    return Content("<span class=\"text-info glyphicon glyphicon-refresh\"></span> " + EnumStatusWorkflow.Reprocessamento.ToString());
                case EnumStatusWorkflow.Reprocessado:
                    return Content("<span class=\"text-primary glyphicon glyphicon-transfer\"></span> " + EnumStatusWorkflow.Reprocessado.ToString());
                default:
                    return Content("-");
            }
        }

        public ActionResult UsuarioAprovacao(Workflow workflow, string usuarioId)
        {
            var ultimaAcaoInicioFluxo = workflow.Aprovacoes
                .Where(a => a.Status != (int)EnumStatusWorkflow.Aprovado)
                .OrderBy(o => o.DataHoraAprovacao)
                .LastOrDefault();

            var aprovacoesVigentes = workflow.Aprovacoes
                .Where(a => a.Status == (int)EnumStatusWorkflow.Aprovado &&
                            a.UsuarioID == usuarioId &&
                            (ultimaAcaoInicioFluxo == null || a.DataHoraAprovacao > ultimaAcaoInicioFluxo.DataHoraAprovacao))
                .ToList();

            if (aprovacoesVigentes.Any())
            {
                return Content("<span class=\"text-success glyphicon glyphicon-ok\"></span>");
            }

            return Content(string.Empty);
        }

        private List<Usuario> CarregarProximosAprovadores(Workflow workflow)
        {
            var ultimaAcaoInicioFluxo = workflow.Aprovacoes
                .Where(a => a.Status != (int)EnumStatusWorkflow.Aprovado)
                .OrderBy(o => o.DataHoraAprovacao).LastOrDefault();

            var aprovacoesVigentes = workflow.Aprovacoes
                .Where(a => a.Status == (int)EnumStatusWorkflow.Aprovado &&
                            (ultimaAcaoInicioFluxo == null ||
                            a.DataHoraAprovacao > ultimaAcaoInicioFluxo.DataHoraAprovacao))
                .ToList();

            var proximaCategoriaGrupo = workflow.CategoriaWorkflow.CategoriaGrupos
                .OrderBy(o => o.sequenciaAprovacao)
                .Where(c => c.Usuarios.Any(u => aprovacoesVigentes == null ||
                                                !aprovacoesVigentes.Select(a => a.Usuario).Contains(u)))
                .FirstOrDefault();

            if (proximaCategoriaGrupo == null)
            {
                return null;
            }

            var proximosUsuariosAprovadores = proximaCategoriaGrupo.Usuarios
                .Where(u => !aprovacoesVigentes.Select(a => a.Usuario).Contains(u))
                .ToList();

            return proximosUsuariosAprovadores;
        }

        private bool ExibeControlesAprovacao(Workflow workflow)
        {
            var ultimaAcao = workflow.Aprovacoes.OrderBy(o => o.DataHoraAprovacao).LastOrDefault();
            if (ultimaAcao == null ||
                ultimaAcao.Status == (int)EnumStatusWorkflow.Reprovado ||
                ultimaAcao.Status == (int)EnumStatusWorkflow.Reprocessamento ||
                ultimaAcao.Status == (int)EnumStatusWorkflow.Cancelado)
            {
                return false;
            }

            var proximosUsuariosAprovadores = this.CarregarProximosAprovadores(workflow);
            if (proximosUsuariosAprovadores == null)
            {
                return false;
            }

            var usuario = db.Users.Find(User.Identity.GetUserId());

            return proximosUsuariosAprovadores.Contains(usuario);
        }

        private bool AprovaConsolidado(Workflow workflow)
        {
            var proximosUsuariosAprovadores = this.CarregarProximosAprovadores(workflow);

            return proximosUsuariosAprovadores == null || !proximosUsuariosAprovadores.Any();
        }

        private bool PermiteReprocessamento(Workflow workflow)
        {
            var ultimaAcao = workflow.Aprovacoes.OrderBy(o => o.DataHoraAprovacao).LastOrDefault();

            return ultimaAcao == null ||
                   ultimaAcao.Status != (int)EnumStatusWorkflow.Reprocessamento;
        }
    }
}
